home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / hypercrd / hc1_2_x / fretext1.sit / Free Text Source Code / appendDeleteFiles 0.71.c next >
Text File  |  1990-01-27  |  7KB  |  286 lines

  1. /* HyperCard XFCN to append or delete files - source code
  2.  * copyright 1990 Mark ^Zimmermann
  3.  *
  4.  * part of the Free Text HyperCard package as an additional tool for
  5.  * database creation and navigation...
  6.  *
  7.  * Call this XFCN as "appendDeleteFiles (cmd)".  If cmd begins with the
  8.  * letter 'A', then a standard files dialog will offer a list of files
  9.  * of any type; if one is selected, then the offer will be repeated and
  10.  * subsequent selections will be appended to the end of the first
  11.  * one.  If cmd begins with the letter 'D', then files selected from
  12.  * the std files dialog (which shows all files types)
  13.  * will be irreversably (probably? barring low-level magic) deleted.
  14.  *
  15.  * Error checking is minimal, and the usual response to an error is
  16.  * to quit with some short message and a beep....
  17.  */
  18.  
  19.  
  20. #include <MacTypes.h>
  21. #include <FileMgr.h>
  22. #include <StdFilePkg.h>
  23. #include <HyperXCmd.h>
  24. #include <SetUpA4.h>
  25.  
  26. #define NULL  0
  27.  
  28.  
  29. pascal void main (XCmdBlockPtr paramPtr);
  30. void doAppend (XCmdBlockPtr paramPtr);
  31. void doDelete (XCmdBlockPtr paramPtr);
  32. int appendNextFile (int baseFileRefNum, Str255 *nextFileName,
  33.   int nextVolRefNum, char *bufp, long myBufSize, XCmdBlockPtr paramPtr);
  34. int adzGetFile (Str255 *fileNamePtr, int *volRefNumPtr, int numTypes);
  35. void returnErrorMsg (XCmdBlockPtr paramPtr, char *msg);
  36. char *strcpy (char *s1, char *s2);
  37. int strlen (char *s);
  38.  
  39.  
  40. pascal void main (paramPtr)
  41.   XCmdBlockPtr paramPtr;
  42.   {
  43.       RememberA0 ();
  44.     SetUpA4();
  45.     switch (**(paramPtr->params[0]))
  46.       {
  47.           case 'A':
  48.               doAppend (paramPtr);
  49.               break;
  50.           case 'D':
  51.               doDelete (paramPtr);
  52.               break;
  53.           default:
  54.               returnErrorMsg (paramPtr,
  55.                 "{Sorry, unrecognized command in appendDeleteFiles call!}");
  56.               break;
  57.       }
  58.     RestoreA4();
  59.     return;
  60.   }
  61.  
  62.  
  63. /* function to do the work of appending files to the end of the
  64.  * first-chosen one... determine buffer size automatically
  65.  */
  66.  
  67. void doAppend (paramPtr)
  68.   XCmdBlockPtr paramPtr;
  69.   {
  70.     Str255 basefileName, nextFileName;
  71.     int baseVolRefNum, baseFileRefNum, nextVolRefNum, nextFileRefNum;
  72.     long myBufSize, grow;
  73.     char *bufp;
  74.     
  75.     if (adzGetFile (&basefileName, &baseVolRefNum, -1))
  76.       {
  77.         if (FSOpen (basefileName, baseVolRefNum, &baseFileRefNum) != noErr)
  78.           {
  79.               returnErrorMsg (paramPtr,
  80.                 "{Sorry, error while trying to open the base file!}");
  81.               return;
  82.             }
  83.  
  84.         /* see how much memory we can get for our buffer here */
  85.         MaxApplZone();
  86.         myBufSize = MaxMem (&grow) - 32768;  /* keep 32kB in reserve */
  87.         if ((bufp = NewPtr (myBufSize)) == NULL)
  88.           {
  89.               returnErrorMsg (paramPtr,
  90.                 "{Sorry, memory manager error while getting buffer space!}");
  91.               return;
  92.             }
  93.  
  94.         while (adzGetFile (&nextFileName, &nextVolRefNum, -1) &&
  95.             appendNextFile (baseFileRefNum, &nextFileName, nextVolRefNum,
  96.                                 bufp, myBufSize, paramPtr))
  97.             ;
  98.  
  99.         DisposPtr (bufp);
  100.         FSClose (baseFileRefNum);
  101.       }
  102.  
  103.     return;
  104.   }
  105.  
  106.  
  107. /* function to do the work of deleting files as they are chosen ... no
  108.  * particular error checking, just try to do it until 'Cancel' ... beep
  109.  * and return a polite message if unable to comply for some reason....
  110.  */
  111.  
  112. void doDelete (paramPtr)
  113.   XCmdBlockPtr paramPtr;
  114.   {
  115.     Str255 fileName;
  116.     int volRefNum;
  117.  
  118.     while (adzGetFile (&fileName, &volRefNum, -1))
  119.         if (FSDelete (fileName, volRefNum) != noErr)
  120.           {
  121.               returnErrorMsg (paramPtr,
  122.                 "{Sorry, file system error while trying to delete a file!}");
  123.               break;
  124.             }
  125.     
  126.     return;
  127.   }
  128.  
  129.  
  130. /* routine to append the contents of nextFile X to baseFile ... does some
  131.  * limited error checking and tries to get a polite msg back to user if
  132.  * there is a problem ... returns 1 if all is well, 0 on error....
  133.  */
  134.  
  135. int appendNextFile (baseFileRefNum, nextFileName, nextVolRefNum,
  136.                         bufp, myBufSize, paramPtr)
  137.   int baseFileRefNum, nextVolRefNum;
  138.   Str255 *nextFileName;
  139.   char *bufp;
  140.   long myBufSize;
  141.   XCmdBlockPtr paramPtr;
  142.   {
  143.     int nextFileRefNum, errNum;
  144.     long count;
  145.     
  146.     errNum = FSOpen (nextFileName, nextVolRefNum, &nextFileRefNum);
  147.     if (errNum != noErr && errNum != opWrErr)    /* ok if read-only here */
  148.       {
  149.         returnErrorMsg (paramPtr,
  150.            "{Sorry, error while attempting to open file to be appended!}");
  151.          return (0);
  152.        }
  153.  
  154.     if (SetFPos (nextFileRefNum, fsFromStart, 0L) != noErr)
  155.       {
  156.         returnErrorMsg (paramPtr,
  157.            "{Sorry, error setting pointer in file to be appended!}");
  158.           FSClose (nextFileRefNum);
  159.           return (0);
  160.       }
  161.     if (SetFPos (baseFileRefNum, fsFromLEOF, 0L) != noErr)
  162.       {
  163.         returnErrorMsg (paramPtr,
  164.            "{Sorry, error setting pointer to end of base file!}");
  165.           FSClose (nextFileRefNum);
  166.           return (0);
  167.       }
  168.     for (;;)
  169.       {
  170.         count = myBufSize;
  171.         errNum = FSRead (nextFileRefNum, &count, bufp);
  172.         if (errNum != noErr && errNum != eofErr)
  173.           {
  174.             returnErrorMsg (paramPtr,
  175.                "{Sorry, error while reading from file to be appended!}");
  176.               FSClose (nextFileRefNum);
  177.               return (0);
  178.           }
  179.         if (count == 0)
  180.             break;
  181.         if (FSWrite (baseFileRefNum, &count, bufp) != noErr)
  182.           {
  183.             returnErrorMsg (paramPtr,
  184.                "{Sorry, error while writing to base file!}");
  185.               FSClose (nextFileRefNum);
  186.               return (0);
  187.           }
  188.       }
  189.     FSClose (nextFileRefNum);
  190.     return (1);                    /* success, at last! */
  191.   }
  192.  
  193.  
  194. /* this routine gets the name of the file to be appended or deleted ...
  195.  * pass it numTypes = 1 for restricting the Std Files Dialog view
  196.  * to type 'TEXT' only, or pass numTypes = -1 to show all files.
  197.  * The function returns 1 if a file was selected (and copies the file
  198.  * name into the place pointed to by fileNamePtr and the volume number
  199.  * into the place pointed to by volRefNumPtr), and returns 0 if the
  200.  * user chooses 'Cancel'....
  201.  */
  202.  
  203. int adzGetFile (fileNamePtr, volRefNumPtr, numTypes)
  204.   Str255 *fileNamePtr;
  205.   int *volRefNumPtr;
  206.   int numTypes;
  207.   {
  208.     SFTypeList myFileTypes;
  209.     Point SFGwhere;
  210.     SFReply myReply;
  211.     register int i;
  212.  
  213.     SFGwhere.v = 90;
  214.     SFGwhere.h = 82;
  215.     myFileTypes[0] = 'TEXT';
  216.     
  217.     SFGetFile (SFGwhere, "\p", 0L, numTypes, myFileTypes, 0L, &myReply);
  218.     
  219.     if (myReply.good)
  220.       {
  221.         for (i = *myReply.fName; i >= 0; --i)
  222.             (*fileNamePtr)[i] = myReply.fName[i];
  223.         *volRefNumPtr = myReply.vRefNum;
  224.         return (1);
  225.       }
  226.     else
  227.         return (0);
  228.   }
  229.  
  230.  
  231. /* function to set the return value of the XFCN to a chosen error msg;
  232.  * if there isn't enough free memory to give us a Handle to the msg,
  233.  * beep a few more times and then return!
  234.  */
  235.  
  236. void returnErrorMsg (paramPtr, msg)
  237.   XCmdBlockPtr paramPtr;
  238.   char *msg;
  239.   {
  240.     Handle answer;
  241.     int msgLength;
  242.     
  243.     SysBeep (10);
  244.     msgLength = strlen (msg);
  245.     if ((answer = NewHandle (1 + msgLength)) == NULL)
  246.       {
  247.         SysBeep (10);
  248.         SysBeep (10);
  249.         return;
  250.       }
  251.  
  252.     strcpy (*answer, msg);
  253.     paramPtr->returnValue = answer;
  254.     return;
  255.   }
  256.  
  257.  
  258. /* function to determine the length of a string ... standard thing,
  259.  * adapted from K&R p.98 ....
  260.  */
  261.  
  262. int strlen (s)
  263.   register char *s;
  264.   {
  265.     char *s0 = s;
  266.  
  267.     while (*s++)
  268.         ;
  269.     return (s - s0 - 1);
  270.   }
  271.  
  272.  
  273. /* function to copy a string from one place to another, in a rather
  274.  * obvious fashion ... adapted from K&R p.101 ....
  275.  */
  276.  
  277. char *strcpy (s1, s2)
  278.   register char *s1, *s2;
  279.   {
  280.     char *s = s1;
  281.     
  282.     while (*s1++ = *s2++)
  283.         ;
  284.     return (s);
  285.   }
  286.